package com.hoopchina.ui.main;

import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Stack;
import com.hoopchina.MainActivity;
import com.hoopchina.news.R;
import com.hoopchina.ui.download.DownloadActivity;
import android.app.Activity;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;

/**
 * View manager of whole UI structure<br/><br/>
 * All views in this application are created from corresponding activity instance
 *   so to speak no matter what the starting type is, the view will be alive during
 *   the whole life of this application<br/><br/>
 * In order to manage every activity starting actions, this view manager is designed
 *   as a singleton instance which can be accessed from all activities
 * Once view manager gets the requests from activities, it retrieves view instance from
 *   MainActivity and adds the view instance to mainAct's view container.<br/><br/>
 * Also this view manager records a view stack for multiple level navigation
 * 
 * ViewManager
 * 所有ui的管理类
 * 
 * @author Neusoft
 */
public class ViewManager {
	private static ViewManager      mInstance = null;         // singleton instance
    private LinearLayout            mContainer;               // reference to mainAct's container
    private MainActivity            mMainAct;                 // reference to main activity
    private ViewHistoryItem         mCurrentViewItem;             // current view item
    private HashMap<Integer, Stack<ViewHistoryItem>>  
                                    mViewHistory;             // history of navigated view items
    
    private IInitListener           mInitListener;            // reference to initialization listener
    private Activity mNextAct;
    private Activity mCurrentAct;
    
    private Animation                                mAnimOpenEnter;
    private Animation                                mAnimOpenExit;
    private Animation                                mAnimCloseEnter;
    private Animation                                mAnimCloseExit;
    
    // constructor
    private ViewManager() {
    	mViewHistory = new HashMap<Integer, Stack<ViewHistoryItem>>();
    	for ( int i = 0; i < TabBarButtonId.EMax; ++i ) {
    		mViewHistory.put( i, new Stack<ViewHistoryItem>() );
    	}
    	mCurrentViewItem = new ViewHistoryItem( null, "", false );
    }
    
    // Singleton portal
	public static ViewManager getInstance() {
		if ( mInstance == null ) {
			synchronized( ViewManager.class ) {
				if ( mInstance == null ) {
					mInstance = new ViewManager();
				}
			}
		}
		return mInstance;
	}
		
	/**
	 * Set view container
	 * @param aContainer reference to view container from mainAct
	 */
	public void setContainer( LinearLayout aContainer ) {
		mContainer = aContainer;
	}
	
	/**
	 * Set main activity
	 * @param aMainAct reference to main activity
	 * @param aInitListener reference to initialization listener
	 */
	public void setMainActivity( MainActivity aMainAct, IInitListener aInitListener ) {
		mMainAct = aMainAct;
		mInitListener = aInitListener;
		
        mAnimOpenEnter = AnimationUtils.loadAnimation( mMainAct, R.anim.openenter );
        mAnimOpenExit = AnimationUtils.loadAnimation( mMainAct, R.anim.openexit );
        mAnimCloseEnter = AnimationUtils.loadAnimation( mMainAct, R.anim.closeenter );
        mAnimCloseExit = AnimationUtils.loadAnimation( mMainAct, R.anim.closeexit );
        
	}
	
	/**
	 * Set the current activity by the activity that rightly switched to
	 * @param aActivity this pointer of current activity
	 */
	public void setCurrentActivity( Activity aActivity ) {
		// this function is called earlier than showViewById, where we save the current view to history
		//    that is, we have temporarily save the new activity info
		// interestingly (and sadly) during the first running of new_task view,
		//    actually this function will be the later one!
		//    so to speak this can cause null pointer crash...because no chance to set _currentView
	    Log.d("DownloadActivity","setCurrentActivity() aActivity = "+aActivity);
	    mNextAct = aActivity;
		// workaround for problem above
		if(mCurrentAct == null){
		    mCurrentAct = aActivity;
		}
	}
	
	/**
	 * Get reference to current activity
	 * @return current activity
	 */
	public Activity getCurrentActivity() {
		return mCurrentAct;
	}
	
	/**
	 * Show a new view with new task property
	 * @param aId activity Id
	 * @param aNeedNavigatedBack if current view will be navigated back
	 * @param aBundle data bundle
	 */
	public void showView( String aId, Class<?> aType, boolean aNeedNavigatedBack, Bundle aBundle ) {
		showViewById( aId, aType, false, aNeedNavigatedBack, aBundle, false, false );
	}
	
	public void showView( String aId, Class<?> aType, boolean aNeedNavigatedBack, Bundle aBundle, boolean aTabChanging ) {
		showViewById( aId, aType, false, aNeedNavigatedBack, aBundle, false, aTabChanging );
	}
	
	/**
	 * Show a new view with clear on top property
	 * @param aId activity Id
	 * @param aNeedNavigatedBack if current view will be navigated back
	 * @param aBundle data bundle
	 */
	public void showClearOnTopView( String aId, Class<?> aType, boolean aNeedNavigatedBack, Bundle aBundle ) {
		// not necessary now, but if you want to keep track of the view instance, comment following out
//		if ( _currentView.getViewId() != null ) {
//			destroyViewById( _currentView.getViewId() );
//		}
		showViewById( aId, aType, true, aNeedNavigatedBack, aBundle, false, false );
	}
	
	/**
	 * 
	 * @param aId
	 * @param aType
	 * @param aBundle
	 * @param aTo
	 */
	public void showViewAndChangeTab( String aId, Class<?> aType, Bundle aBundle, int aTo ) {
		getCurrentHistory().push( new ViewHistoryItem( mCurrentViewItem ) );
		Bundle bundle;
		if(aBundle == null){
			bundle = new Bundle();
			bundle.putInt( "from", getFocusedTabBarButton() );
		}else{
			bundle = aBundle;
			bundle.putInt( "from", getFocusedTabBarButton() );
		}
		
		Stack<ViewHistoryItem> targetStack = mViewHistory.get( aTo );
		if ( targetStack.size() > 0 && targetStack.peek().getViewId() == aId ) {
	    	ViewHistoryItem viewItem = mViewHistory.get( aTo ).pop();
			if ( viewItem != null ) {
				showViewById( 
						viewItem.getViewId(),
						viewItem.getType(),
						false, 
						false,
						bundle,
						false,
						false );
			}
		}
		else {
			showViewById( 
					aId,
					aType,
					true, 
					false,
					bundle,
					false,
					false );
		}
		mMainAct.setFocusedButton( aTo );
	}
	
	/**
	 * If navigating back is allowed
	 * @return yes or no
	 */
	public boolean canGoBack() {
		boolean ret = false;
		if ( getCurrentHistory().size() > 0 ) {
			ret = true;
		}
		return ret;
	}
	

	/**
	 * Go back to previous view with data bundle
	 * @param aBundle data bundle
	 * @throws EmptyStackException
	 */
	public void goBack( Bundle aBundle ) throws EmptyStackException {
		try {
			ViewHistoryItem viewItem = getCurrentHistory().pop();
			showViewById( 
					viewItem.getViewId(),
					viewItem.getType(),
					viewItem.getIsOnTop(), 
					false, 
					aBundle,
					true,
					false );
		}
		catch( EmptyStackException ex ) {
			throw ex;
		}
	}
	
	/**
	 * Go back to previous view without data bundle
	 */
	public void goBack() {
		goBack( null );
	}
	
	/**
	 * 
	 * @param aTo
	 */
	public void goBackAndChangeTab( int aTo ) {
		mMainAct.setFocusedButton( aTo );
		goBack();
	}
	
	/**
	 * Clear view history
	 */
	public void clearViewHistory() {
		if ( mViewHistory.size() > 0 ) {
			mViewHistory.clear();
		}
	}
	
	/**
	 * Remove one view from current view container
	 * @param aView reference to view
	 */
	public void destroyView( View aView ) {
		mContainer.removeView( aView );
	}
	
	/**
	 * Remove all views from current view container
	 */
	public void removeAllViews() {
		mContainer.removeAllViews();
	}
	
	/**
	 * Clear all data in view container and current view instance
	 */
	public void finish() {
		removeAllViews();
		mCurrentViewItem = new ViewHistoryItem( null, "", false );
		mCurrentAct = null;
		mNextAct = null;
	}
	
	/**
	 * Set title bar text
	 * @param aTitle title string
	 */
	public void setTitle( String aTitle ) {
		mMainAct.setTitle( aTitle );
	}
	
	public void setTitle( int aTitle ) {
		mMainAct.setTitle( aTitle );
	}
	
	/**
	 * Set title bar status
	 * @param aStatus status text
	 */
	public void setStatus( String aStatus ) {
		mMainAct.setStatus( aStatus );
	}
    
    /**
     * Set title bar primary button
     * @param aListener
     */
    public void setPrimaryButton( OnClickListener aListener ) {
    	mMainAct.setPrimaryButton( aListener );
    }
	
	/**
	 * Set title bar back button
	 * @param aVisible if button will be visible
	 * @param aListener the button click listener
	 */
	public void setBackButton( String aText, OnClickListener aListener ) {
		mMainAct.setBackButton( aText, aListener );
	}
	
	/**
	 * Set title bar assist button
	 * @param aText the button text
	 * @param aListener the button click listener
	 */
	public void setAssistButton( String aText, int aBgResource, OnClickListener aListener ) {
		mMainAct.setAssistButton( aText, aBgResource, aListener );
	}
	
	public void setNextButton( OnClickListener aListener ) {
		mMainAct.setNextButton(aListener);
	}
	
	public void setPreButton( OnClickListener aListener ) {
		mMainAct.setPreButton(aListener);
	}
	
	/**
	 * 
	 */
	public void hideLeftButton() {
		mMainAct.hideLeftButton();
	}
    public void showDetailViewBar(boolean isDisp) {
    	mMainAct.showDetailViewBar(isDisp);
    }
    
    
    

	/**
	 * Get the initialization listener
	 * @return reference to initialization listener
	 */
	public IInitListener getInitListener() {
		return mInitListener;
	}
    
    /**
     * Set tab bar visibility
     * @param aVisible
     */
    public void setTabBarVisibility( boolean aVisible ) {
    	mMainAct.setTabBarVisibility( aVisible );
    }    
    
    /**
     * Set Title bar visibility
     * @param aVisible
     */
    public void setTitleBarVisibility( boolean aVisible ) {
    	mMainAct.setTitleBarVisibility( aVisible );
    }    
    
	/**
     * 城市选择
     * @param resultNum
     */
    public void citySelect(int resultNum,ILocalNewsChanged localNewsChanged) {
    	mMainAct.citySelect(resultNum,localNewsChanged);
    }
    /**
     * Set the focused tab bar button
     * @param aButtonIndex
     */
    public void setFocusedButton( int aButtonIndex ) {
    	mMainAct.setFocusedButton( aButtonIndex );
    }
    
    /**
     * 
     * @return
     */
    public int getFocusedTabBarButton() {
    	return mMainAct.getFocusedTabBarButtonIndex();
    }
    
    /**
     * Tab changed handler, start activity if history got one (should always be!)
     *   or let main activity handle this
     * @param aToIndex
     * @return
     */
    public boolean onTabBarFocusedButtonChanged( int aToIndex ) {
    	boolean handled = false;
		getCurrentHistory().push( new ViewHistoryItem( mCurrentViewItem ) );
    	ViewHistoryItem viewItem = null;
    	try {
    		viewItem = mViewHistory.get( aToIndex ).pop();
    	}
    	catch( EmptyStackException ex ) {
    		ex.printStackTrace();
    	}
		if ( viewItem != null ) {
			mMainAct.setFocusedButton( aToIndex );
			showViewById( 
					viewItem.getViewId(),
					viewItem.getType(),
					viewItem.getIsOnTop(), 
					false,
					null,
					false,
					true );
			handled = true;
		}
		return handled;
    }
    
    public void restoreTab( int aIndex ) {
    	mViewHistory.get( aIndex ).clear();
    }
    
    public void toggleFullScreen() {
    	mMainAct.toggleFullScreen();
    }
    public void doAnimOnTitleBar( boolean aEnabled ) {
    	mMainAct.doAnimOnTitleBar(aEnabled);
    }
	
	/**
	 * Get view instance by Id
	 * @param aId activity Id
     * @param aIsOnTopView if activity is clear_top view or new_task view
     * @param aBundle the data bundle
	 * @return view instance
	 */
	private View getViewById( String aId, Class<?> aType, boolean aIsOnTopView, Bundle aBundle ) {
		return mMainAct.getViewByProperties( aId, aType, aIsOnTopView, aBundle );
	}
	
	/**
	 * Show a new view with multiple properties
	 * @param aId activity Id
	 * @param aType
	 * @param aIsOnTopView clean on top view or new task view
	 * @param aNeedNavigatedBack if current view will be navigated back
	 * @param aBundle data bundle
	 * @param isBacking
	 * @param isTabChanging
	 */
	private void showViewById( String aId, Class<?> aType, boolean aIsOnTopView, 
			boolean aNeedNavigatedBack, Bundle aBundle,
			boolean isBacking, boolean isTabChanging ) {
	    
		if ( aId.equals( mCurrentViewItem.getViewId() ) ) {
			// already showing the same activity, ignore request
			return;
		}
		
		// old view animation transitions
		if ( mCurrentViewItem != null && mCurrentAct != null &&
				!isTabChanging ) { // we're not showing animation when tab changing
			View oldView = mCurrentAct.getWindow().getDecorView();
			if ( isBacking ) {
				animateCloseExit( oldView );
			}
			else {
				animateOpenExit( oldView );
			}
		}
		
		removeAllViews(); // = LinearLayout::removeAllViews();
		View view = getViewById( aId, aType, aIsOnTopView, aBundle );
		if ( view != null ) {
			// now handles new view's animation transition
			if ( !isTabChanging ) { // we're not showing animation when tab changing
				if ( isBacking ) {
					animateCloseEnter( view );
				}
				else {
					animateOpenEnter( view );
				}
			}
			mContainer.addView( view );
//            if ( mCurrentViewItem.getIsOnTop() ) {
//                mMainAct.getLocalActivityManager().destroyActivity( mCurrentViewItem.getViewId(), false );
//            }
		}
		
        boolean sameView = ( getCurrentHistory().size() > 0 && 
                getCurrentHistory().peek().getViewId().equals( mCurrentViewItem.getViewId() ) );
        // for view won't need to be navigated back, it's not necessary to add them to history stack
        if ( aNeedNavigatedBack && !sameView ) {
            // create an exact copy of current view because stack only saves references to objects.
            getCurrentHistory().push( new ViewHistoryItem( mCurrentViewItem ) );
            // later pointer to current activity will be set later during Activity::onCreated();
        }
		mCurrentAct = mNextAct;
		mCurrentViewItem = new ViewHistoryItem( aType, aId, aIsOnTopView );
	}
	
	/**
	 * Get current history stack
	 * @return
	 */
	private Stack<ViewHistoryItem> getCurrentHistory() {
		int index = getFocusedTabBarButton();
		return mViewHistory.get( index );
	}
	
    
    /**
     * Called to animate appearance of this activity 
     * as if somebody clicked next on previous activity 
     * and ended up to this activity.
     * 
     * Animation:  |<--
     */
	private void animateOpenEnter( View aView ) { 
	    aView.startAnimation( mAnimOpenEnter );
    }

    /**
     * Called to animate appearance of this activity 
     * as if somebody clicked back on previous activity 
     * and ended up to this activity.
     * 
     * Animation:  -->| 
     */
    private void animateCloseEnter( View aView ) {
        aView.startAnimation( mAnimCloseEnter );
    }   

    /**
     * Called to animate disappearance of this activity 
     * when "next" button was clicked
     * 
     * Animation:  <--|
     */
    private void animateOpenExit( View aView ) {   
        aView.startAnimation( mAnimOpenExit );
    }


    /**
     * Called to animate disappearance of this activity 
     * when "back" button was clicked
     * 
     * Animation:  |--> 
     */ 
    private void animateCloseExit( View aView ) { 
        aView.startAnimation( mAnimCloseExit );
    }

    /**
     * 
     * @param animAttributeId
     */
    @SuppressWarnings ( "unused" )
    private void animateTransition( View aView, int aAnimAttributeId ) {       
        TypedValue animations = new TypedValue();       
        Theme theme = mMainAct.getTheme();

        theme.resolveAttribute( android.R.attr.windowAnimationStyle, animations, true );      
        TypedArray animationArray = mMainAct.obtainStyledAttributes( animations.resourceId, 
                                                            new int[] { aAnimAttributeId } );

        int animResId = animationArray.getResourceId( 0, 0 );
        animationArray.recycle();

        if( animResId != 0 ) {
            try {
                Animation anim = AnimationUtils.loadAnimation( mMainAct, animResId );             
                aView.startAnimation( anim );
            }
            catch( Resources.NotFoundException ex ) {
            	// ignore this exception
            }
        }               
    }
    
    /**
     * 
     */
    public void displayWeatherBox(boolean isDisp) {
        mMainAct.displayWeatherBox(isDisp);
    }
    
    public void showRefreshButton(boolean isshow){
    	mMainAct.ShowTitleBarRefreshbutton(isshow);
    }
    
      public void hideTitleBarRefreshbutton(boolean isshow){
    	mMainAct.hideTitleBarRefreshbutton(isshow);
    }
      
    public void showSubscriptionBtn(boolean isshow ){
    	mMainAct.showSubscriptionBtn(isshow);
    }
    
    public void showGraphicSelectBtn(boolean isshow){
    	mMainAct.showGraphicSelectBtn(isshow);
    }
    
    public void showCategoryReadBtn(boolean isshow){
    	mMainAct.showCategoryReadBtn(isshow);
    }
    
	public void showAssistButton(boolean isshow ){
		mMainAct.ShowAssistButton(isshow);   
	}
	
	public void showLoadingProgressBar( boolean isshow ){
		mMainAct.ShowLoadingProgressBar(isshow);
	}
	
	public void showNextButton( boolean isshow ){
		mMainAct.showNextButton(isshow);
	}
	
	public void showPreButton( boolean isshow ){
		mMainAct.showPreButton(isshow);
	}
	
	public void setSubscriptionBtnOnClickerLister(OnClickListener aListener){
		mMainAct.setSubscriptionBtnOnClickerLister(aListener);
	}
	
	public void setGraphicSelectBtnOnClickerLister(OnClickListener aListener){
		mMainAct.setGraphicSelectBtnOnClickerLister(aListener);
	}
	
	public void setCategoryReadBtnOnClickerLister(OnClickListener aListener){
		mMainAct.setCategoryReadBtnOnClickerLister(aListener);
	}

	public void refreshWeatherBoxCity() {
		// TODO Auto-generated method stub
		mMainAct.refreshWeatherBoxCity();
	}
	public void setUserGuideImage(int resid) {
		mMainAct.setUserGuideImage(resid);
	}
	
	public void setUserGuideVisibility(int visibility) {
		mMainAct.setUserGuideVisibility(visibility);
	}
	public boolean isDispUserGuide() {
		return mMainAct.isDispUserGuide();
	}
	public void setUserGuideOnClickListener(OnClickListener listener) {
		mMainAct.setUserGuideOnClickListener(listener);
	}

}
